﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using leviathan.player;
using leviathan.enemy;

namespace leviathan.combat
{
    public class CombatClass
    {
        public struct attackmode
        {
            public string name;
            public Int16 poseffect;
            public Int16 negeffect;
        }

        private Int16 hp;
        private Int16 mana;
        private attackmode mode1;
        private attackmode mode2;
        private attackmode mode3;
        private Int16 hpPotion;
        private Int16 manaPotion;

        //Form
        private System.Windows.Forms.Form form;
        private System.Windows.Forms.Button but1;
        private System.Windows.Forms.Button but2;
        private System.Windows.Forms.Button but3;
        private System.Windows.Forms.TextBox text;

        //Actors
        private Player player;
        private Enemy mob;
        private supervisor.Supervisor.CombatState status;

        public CombatClass(Player p1, string mobname, System.Windows.Forms.Button b1, System.Windows.Forms.Button b2, System.Windows.Forms.Button b3, System.Windows.Forms.TextBox tb, System.Windows.Forms.Form form1)
        {
            status = supervisor.Supervisor.CombatState.inner;
            hpPotion = 1;
            manaPotion = 1;
            player = p1;
            //Class update
            hp = player.getHp();
            mana = player.getMana();
            loadComponents(player.getProf());
            //Enemy update
            mob = new Enemy(mobname);
            //Form update
            form = form1;
            but1 = b1;
            but2 = b2;
            but3 = b3;
            text = tb;
        }

        private void loadComponents(string type)
        {
            if (System.IO.File.Exists("../../Defaults/" + type + "Fight.def"))
            {
                using (System.IO.StreamReader sr = new System.IO.StreamReader("../../Defaults/" + type + "Fight.def"))
                {
                    mode1.name = sr.ReadLine();
                    mode1.poseffect = Convert.ToInt16(sr.ReadLine());
                    mode1.negeffect = Convert.ToInt16(sr.ReadLine());
                    mode2.name = sr.ReadLine();
                    mode2.poseffect = Convert.ToInt16(sr.ReadLine());
                    mode2.negeffect = Convert.ToInt16(sr.ReadLine());
                    mode3.name = sr.ReadLine();
                    mode3.poseffect = Convert.ToInt16(sr.ReadLine());
                    mode3.negeffect = Convert.ToInt16(sr.ReadLine());
                    sr.Close();
                }
            }
            else
            {
                System.Windows.Forms.MessageBox.Show("Hiányzó fájl! (AttackMode)", "Hiba!");
                return;
            }
        }

        public void setAuto(bool logical)
        {
            while(!endCheck())
            {
                //Módválasztás
                attackmode select;

                if (hp > player.getHp() * 0.75)
                {
                    if (mob.HpRate() > 0.5)
                    {
                        Random rnd = new Random();
                        int tmp = rnd.Next(0, 6);

                        if (tmp < 2)
                        {
                            select = mode1;
                        }
                        else
                        {
                            select = mode2;
                        }
                    }
                    else
                    {
                        select = mode2;
                    }
                }
                else if (hp > player.getHp() * 0.5)
                {
                    Random rnd = new Random();
                    int tmp = rnd.Next(0, 6);

                    if (tmp < 2)
                    {
                        select = mode1;
                    }
                    else if (tmp < 5)
                    {
                        select = mode2;
                    }
                    else
                    {
                        select = mode3;
                    }
                }
                else if (hp > player.getHp() * 0.25)
                {
                    Random rnd = new Random();
                    int tmp = rnd.Next(0, 9);

                    if (tmp < 2)
                    {
                        select = mode1;
                    }
                    else if (tmp < 6)
                    {
                        select = mode2;
                    }
                    else
                    {
                        select = mode3;
                    }
                }
                else
                {
                    Random rnd = new Random();
                    int tmp = rnd.Next(0, 6);

                    if (tmp < 1)
                    {
                        select = mode2;
                    }
                    else
                    {
                        select = mode3;
                    }
                }

                //Mana ellenőrzés
                if (select.negeffect > mana)
                {
                    if (mode1.negeffect < mana)
                    {
                        select = mode1;
                    }
                }

                myAttack(select);
                itsAttack();
            }

            form.SendToBack();
            form.Close();
        }
        
        private bool priorityCheck()
        {
            if (player.getQuickness() > mob.getQuickness())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool endCheck()
        {
            if (hp <= 0)
            {
                status = supervisor.Supervisor.CombatState.endDefeat;
                return true;
            }
            else if (mob.getHp() <= 0)
            {
                status = supervisor.Supervisor.CombatState.endVictory;
                return true;
            }
            else
            {
                status = supervisor.Supervisor.CombatState.inner;
                return false;
            }
        }

        private void myAttack(attackmode a)
        {
            Int16 seged;
            seged = Convert.ToInt16(a.poseffect + player.getAp() - mob.getDp());
            seged = Convert.ToInt16(mob.getHp() - seged);
            mob.setHp(seged);
            text.Text += "Sebeztél " + seged + " életet a következő támadással: " + a.name + Environment.NewLine;

            mana = (Int16)(mana - a.negeffect);
        }

        private void itsAttack()
        {
            Enemy.attackmode s = mob.selectMode();
            Int16 seged2;
            seged2 = Convert.ToInt16(s.poseffect + mob.getAp() - player.getDp());

            if (hp - seged2 < 0)
            {
                hp = (Int16)0;
            }
            else if ((hp - seged2) > player.getHp())
            {
                hp = player.getHp();
            }
            else
            {
                hp = Convert.ToInt16(hp - seged2);
            }
            text.Text += mob.getName() + " sebzett " + seged2 + " életet a következő támadással: " + s.name + Environment.NewLine;
        }

        private void defenseAttack(attackmode a)
        {
            Enemy.attackmode s = mob.selectMode();
            Int16 seged2;
            seged2 = Convert.ToInt16(s.poseffect + mob.getAp() - player.getDp() - a.poseffect);
            if (seged2 > 0)
            {
                if (hp - seged2 < 0)
                    hp = (Int16)0;
                else if (hp - seged2 > player.getHp())
                    hp = player.getHp();
                else
                    hp = Convert.ToInt16(hp - seged2);
                text.Text += mob.getName() + " egy " + s.name + " -val támadott rád de te ügyes védekezéssel " + seged2 + "-re csökkentetted a sérülést." + Environment.NewLine;
            }
            else
            {
                text.Text += mob.getName() + " támadását teljes mértékben ki tudtad védeni!" + Environment.NewLine;
            }
            
            mana = (Int16)(mana - a.negeffect);
        }

        private void normalAttack(attackmode b)
        {
            if (priorityCheck())
            {
                myAttack(b);

                if (mob.getHp() != 0)
                {
                    itsAttack();
                }
            }
            else
            {
                itsAttack();

                if (hp > 0)
                {
                    myAttack(b);
                }
            }
        }

        /// <summary>
        /// Harci mód kiválasztása
        /// </summary>
        /// <param name="i">1=első támadás, 2=második támadás, 3=védekezés</param>
        public void selectMode(int i)
        {
            text.Clear();
            switch (i)
            {
                case 1:
                    if (mode1.negeffect <= mana)
                    {
                        normalAttack(mode1);
                    }
                    else
                        text.Text = "Nincs elég varázserőd a képességed aktiválásához" + Environment.NewLine;
                    break;
                case 2:
                    if (mode2.negeffect <= mana)
                    {
                        normalAttack(mode2);
                    }
                    else
                        text.Text = "Nincs elég varázserőd a képességed aktiválásához" + Environment.NewLine;
                    break;
                case 3:
                    if (mode3.negeffect <= mana)
                    {
                        defenseAttack(mode3);
                    }
                    else
                        text.Text = "Nincs elég varázserőd a képességed aktiválásához" + Environment.NewLine;
                    break;
            }

            if (endCheck())
            {
                form.SendToBack();
                form.Close();
            }
        }

        /// <summary>
        /// Varázsital elfogyasztására szolgáló metódus.
        /// </summary>
        /// <param name="i">Varázsital típusa (1=hpPotion, 2=manaPotion)</param>
        public void selectDrink(int i)
        {
            switch (i)
            {
                case 1:
                    if (hpPotion > 0)
                    {
                        --hpPotion;
                        if (player.getHp() < (Int16)(hp + 50))
                            hp = player.getHp();
                        else
                            hp = (Int16)(hp + 50);
                        text.Text = "Elhasználtál egy életerő italt. Maradt még: " + hpPotion + " db." + Environment.NewLine;
                    }
                    else
                        text.Text = "Megpróbáltál gyorsan előkotorni egy varázsitalt, de már nem volt több a táskádban!" + Environment.NewLine;

                    itsAttack();
                    break;
                case 2:
                    if (manaPotion > 0)
                    {
                        --manaPotion;
                        if (player.getMana() < (Int16)(mana + 50))
                            mana = player.getMana();
                        else
                            mana = (Int16)(mana + 50);
                        text.Text = "Elhasználtál egy varázserő italt. Maradt még: " + manaPotion + " db." + Environment.NewLine;
                    }
                    else
                        text.Text = "Megpróbáltál gyorsan előkotorni egy varázsitalt, de már nem volt több a táskádban!" + Environment.NewLine;

                    itsAttack();
                    break;
            }
        }

        /// <summary>
        /// A harc feladására szolgáló metódus.
        /// </summary>
        public void commitSuicide()
        {
            status = supervisor.Supervisor.CombatState.endDefeat;
            form.SendToBack();
            form.Close();
        }

        /// <summary>
        /// Játékos aktuális életének lekérdezésére szolgáló metódus.
        /// </summary>
        /// <returns>Életerő</returns>
        public Int16 getActHp()
        {
            return hp;
        }

        /// <summary>
        /// Játékos aktuális varázserejének lekérdezésére szolgáló metódus.
        /// </summary>
        /// <returns>Mana</returns>
        public Int16 getActMana()
        {
            return mana;
        }

        /// <summary>
        /// Ellenfél aktuális életének lekérdezésére szolgáló metódus.
        /// </summary>
        /// <returns>Életerő</returns>
        public Int16 getActEHp()
        {
            return mob.getHp();
        }

        /// <summary>
        /// Ellenfél aktuális varázserejének lekérdezésére szolgáló metódus.
        /// </summary>
        /// <returns>Mana</returns>
        public Int16 getActEMana()
        {
            return mob.getMana();
        }

        public attackmode getAttackMode1()
        {
            return mode1;
        }

        public attackmode getAttackMode2()
        {
            return mode2;
        }

        public attackmode getAttackMode3()
        {
            return mode3;
        }

        public Int16 getXp()
        {
            return mob.getXp();
        }

        public string getEName()
        {
            return mob.getName();
        }

        public supervisor.Supervisor.CombatState getState()
        {
            return status;
        }
    }
}
